package day4;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//测试反射编写一个任意对象调用任意方法
public class TestInvokeMethod {
    public static void main(String[] args) {
        test(null);

        Student s = new Student();
        Object value = TestInvokeMethod.base(s, "study");
        System.out.println(value);
        Teacher t = new Teacher();
        Object value2 = TestInvokeMethod.base2(t, "sum", 90, 98);
        System.out.println(value2);
    }

    //method(方法名,形参class[])
    //method.invoke(对象,实参...)
    //参数1：调用方法的对象
    //参数2：方法名称
    //参数3：方法调用传递的实参
    //返回值：表示方法的返回值
    //bug:如果调用了带基本类型的方法 会自动装箱   导致方法不存在...
    //bug:虽然搞定了基本类型参数的bug 但是如果方法重载了呢?
    public static Object base(Object o, String name, Object... params) { //"java",110

        Object value = null;
        try {
            Class c = o.getClass();
            Class[] args = new Class[params.length];
            for (int i = 0; i < params.length; i++) {
                args[i] = params[i].getClass();
            }
            Method m = c.getDeclaredMethod(name, args); //"".getClass()   Integer.getClass
            m.setAccessible(true);
            value = m.invoke(o, params);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return value;
    }

    public static Object base2(Object o, String name, Object... params) {
        Class c = o.getClass();
        Class[] args = null;
        for (Method m : c.getDeclaredMethods()) {
            if (m.getName().equals(name)) {
                args = m.getParameterTypes();
            }
        }
        Object value = null;
        try {
            Method m = c.getDeclaredMethod(name, args);
            m.setAccessible(true);
            value = m.invoke(o, params);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return value;
    }


    public static void test(String[] args) {
        String s = "java";
        System.out.println(s.getClass());
        System.out.println(String.class);
    }
}
